[Java] 접근제한자와 정보 은닉 & Static

접근제한자 (Access Modifier)

클래스, 클래스 내부의 변수/메서드/생성자에 대한 접근 권한 지정.

적용 위치 :

  • 클래스 선언구 : public, default만 사용 가능

    • 주의⚡ : .java 파일 내에 여러 클래스를 생성할 수 있지만, public 클래스는 하나만 존재할 수 있다
  • 변수, 생성자, 메소드 선언구 : 4가지 다 사용 가능
종류 Access 범위
public 모든 곳에서 접근 가능
protected 같은 패키지 내에서 호출 가능, 상속 관계의 하위 클래스에서는 패키지가 달라도 호출 가능
default (생략된 형태) 같은 패키지 내에서만 호출 가능
private 같은 클래스 내에서만 호출 가능

정보 은닉

1) get(), set() 메서드

이전 포스팅에서 봤듯이 클래스 내의 멤버변수를 호출하려면 참조변수.멤버변수 와 같이 참조변수에 도트연산자를 통해 호출하면 된다. 그러나 이렇게 멤버변수를 참조하여 클래스에 직접 접근하는 것은 권장되지 않는다.

예를 들어, Student 클래스의 멤버변수인 studentID는 음수가 될 수 없는 데이터라고 가정하자. 그러나 멤버변수에 직접 접근한다면 음수를 대입해버려도 막을 방법이 없기 때문에 클래스 정보 자체가 훼손될 위험이 있다.

이를 해결하기 위해 멤버변수는 private으로 선언하고, 대신 get, set 메서드를 public으로 선언하여 외부에서 사용할 수 있도록 만들어보자.

⚡ 이클립스 단축키 : alt + shift + s => Generate Getters and Setters… 선택

<Student.java 파일>

public class Student {
	// private 변수로 선언 - 해당 클래스 외 다른 곳에서는 접근 불가
	private int studentID;
	private String studentName;		

	// get메서드 
	public int getStudentID() {
		return studentID;
	}

	// set메서드를 이용해서 값 설정에 제한 둘 수 있음
	public void setStudentID(int studentID) {
		if (studentID > 0) {
			this.studentID = studentID;
		} else {			
			System.out.println("잘못된 값입니다");
		}
	}

	public String getStudentName() {
		return studentName;
	}

	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	
}

<StudentTest.java 파일>

public class StudentTest {

	public static void main(String[] args) {
		Student student1 = new Student();
		Student student2 = new Student();		
						
//	student1.studentID = 10;  오류 발생 (private 변수에 직접 접근 불가)
		student1.setStudentID(-10);
		student2.setStudentID(10);
		
		System.out.println(student1.getStudentID());  // "잘못된 접근입니다"
		System.out.println(student2.getStudentID());  // 10
	}

}

Static

객체(인스턴스) 생성과 상관 없이, 클래스가 메모리에 올라갈 때 자동으로 생성되어 그 값을 모든 인스턴스가 공유함.

사용 위치 :

  • 변수
  • 메소드
  • static 중괄호 { }

1) Static 변수

  • ‘정적 변수’라고도 함.
  • 클래스가 공통으로 사용하는 변수
  • 다른 멤버변수들처럼 객체(인스턴스)가 생성될 때마다 새로 생성되는 게 아니라, 프로그램이 실행되어 메모리에 올라갔을 때 딱 한번 메모리 공간에 할당됨. 그리고 그 값을 클래스의 모든 인스턴스가 공유함

🎈 Student 클래스가 모두 공유하는 serialNum이라는 static 변수를 만들어서, 이를 활용해 Student 객체가 생성될 때마다 학번을 자동으로 부여해보자.

<Student.java 파일>

public class Student {
	public static int serialNum = 1000;  // serialNum 값 초기화
	private int studentID;
	private String studentName;		
	
	// 생성자를 통해 serialNum을 객체가 생성될때마다 1씩 증가시켜서 studentID에 대입시키기
	public Student() {
		serialNum++;
		studentID = serialNum;
	}
	
	public int getStudentID() {
		return studentID;
	}
	
	public String getStudentName() {
		return studentName;
	}

	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	
}

<StudentTest.java> 파일

public class StudentTest {

	public static void main(String[] args) {
		Student student1 = new Student();
		Student student2 = new Student();		
						
		System.out.println(student1.getStudentID());  // 1001
		System.out.println(student2.getStudentID());  // 1002
	}

}

serialNum 변수는 static이기 때문에, 서로 다른 참조변수인 student1, student2가 동일한 serialNum 변수의 메모리를 참조하고 있다. student1 인스턴스가 생성될 때 serialNum의 값은 1001이 되었고, 또다른 student2 인스턴스가 생성될 때 serialNum의 값이 1002가 된 것을 확인할 수 있다.


static 변수는 클래스 이름으로 참조하여 사용할 수 있다.

  • static 변수는 클래스의 모든 인스턴스가 공유하므로, 인스턴스보다 먼저 생성된다.
  • student1.serialNum과 같이 인스턴스로 참조할 수도 있지만, 보통 Student.serialNum 과 같이 클래스 이름으로 직접 참조해서 사용한다.

2) Static 메서드 (= 클래스 메서드)

🌈 어떤 클래스가 메서드의 기능만 수행할 때 (그 클래스의 객체를 만드는 게 의미가 없을때) 그 메서드는 static으로 만들면 된다.

  • 클래스 메서드 내에서는 멤버변수 사용 불가능하다

    : 클래스 메서드는 인스턴스 생성 전에 만들어지기 때문에, 인스턴스가 만들어지는 순간에 생성되는 멤버변수(=인스턴스변수)를 포함할 수 없다.


<Student.java 파일>

public class Student {
	private static int serialNum = 1000;
	private int studentID;
	private String studentName;		
	
	public Student() {
		serialNum++;
		studentID = serialNum;
	}
	
	// 클래스 메서드
	public static int getSerialNum() {
		int i = 10;  // getSerialNum 메서드의 로컬변수는 당연 생성 가능
		// studentName = "김철수";    => 오류 발생. 멤버변수 사용 불가.
		return serialNum;
	}

	public static void setSerialNum(int serialNum) {
		Student.serialNum = serialNum;
	}
	
	public int getStudentID() {
		return studentID;
	}	
	public String getStudentName() {
		return studentName;
	}
	
	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	
}

<StudentTest.java 파일>

public class StudentTest {

	public static void main(String[] args) {
		// static 메서드이므로 객체 생성 전 사용 가능
		System.out.println(Student.getSerialNum());  // 1000
		
		Student student1 = new Student();								
		System.out.println(Student.getSerialNum());  // 1001
		
	}

}

Written by@[hyem]
Hyem's Dev Note

GitHub